package com.enzoism.springboot.dive.chapter01;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 要点一：CompletableFuture::join/CompletableFuture::get方法区别
 * 1) CompletableFuture.get() 和 CompletableFuture.join() 这两个方法是获取异步守护线程的返回值的。
 * 2) get() 方法会抛出经检查的异常，可被捕获，自定义处理或者直接抛出。
 * 3) 而 join() 会抛出未经检查的异常。
 * 缺点：如果代码中可能会抛出【检查异常】那么代码的逻辑要进行大变动（不能再适应lambda表达式-stream流式处理）
 * - 遇到【检查异常】在逻辑处理中进行异常检查判断
 *
 * @link https://blog.csdn.net/admin123404/article/details/111035529
 */
public class TestCompleteFuture3 {
    public static void main(String[] args) {
        ExecutorService cachePool = Executors.newCachedThreadPool();
        // 1、测试CompleteFuture
        Set<List<String>> lists = testCompleteFuture(cachePool);
        lists.stream().forEach(item -> item.forEach(innerItem -> System.out.println("----------->" + innerItem)));

        cachePool.shutdown();
    }

    /**
     * 不用再使用Callable进行业务包装了
     */
    public static Set<List<String>> testCompleteFuture(ExecutorService executorService) {
        List<String> list = Arrays.asList("1", "2", "3", "4", "5");

        //采用Stream流的形式进行处理:supplyAsync同步处理
        List<CompletableFuture<List<String>>> dataFutureList = list.stream().map(item -> CompletableFuture
                .supplyAsync(() -> getRestUrlDataList(item), executorService))
                .collect(Collectors.toList());

        return dataFutureList.stream().map(CompletableFuture::join).collect(Collectors.toSet());
    }

    /**
     * 模拟进行业务处理：此处模拟异常【为受检异常RuntimeException】CompletableFuture::join可以捕获异常
     */
    private static List<String> getRestUrlDataList(String usrId) {
        try {
            TimeUnit.SECONDS.sleep(Integer.valueOf(usrId));
            throw new NullPointerException();
            //return Arrays.asList(usrId, "1111");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return new ArrayList<>();
    }
}
